import numpy as np
import matplotlib.pyplot as plt

SIZE = 10
DIMENTION = 2
SPACE_NUM = pow(SIZE, DIMENTION)

# 解空间中抽取随机点
def pick_one(space):
	return np.random.randint(0, len(space))

# 解空间中抽取相邻点
def pick_next(space, x):
	# 由于这里解空间边长为10，维度为2，就直接简化了
	# 边界处理也简化了，允许跨边界相邻
	move = [-SIZE, SIZE, -1, 1] # 上下左右
	direction = np.random.randint(0, DIMENTION * 2)
	return ((x + move[direction]) + SPACE_NUM) % SPACE_NUM

# 使用蒙特卡洛方法计算解空间平滑度
def calculate_soft(space, sampling_num):
	sum_soft = 0
	for i in range(sampling_num):
		x = pick_one(space) # 解空间中抽取随机点
		y = pick_next(space, x) # 解空间中抽取相邻点
		z = pick_one(space) # 解空间中抽取随机点
		if abs(space[x] - space[y]) < abs(space[x] - space[z]):
			sum_soft += 1
	return float(sum_soft) / sampling_num

# 设置随机数种子，这里可以使用任意整数
np.random.seed(0)
# 生成10 * 10二维解空间
space = []
for i in range(SPACE_NUM):
	space.append(np.random.random())
result = []
for i in range(20):
	sampling_num = pow(2, i) # 抽样次数，越大越精确
	result.append(calculate_soft(space, sampling_num))
# 绘图
fig = plt.figure(figsize=(12, 5))
ax = fig.add_subplot(1, 1, 1)
ax.plot(result, linewidth = 2)
ax.plot([0, 19], [0.5, 0.5], 'r', linewidth = 1)
ax.set_xlabel('Sampling Num')
ax.set_ylabel('Smoothness')
labels = [f'2^{i}' for i in range(20)]
ticks = np.arange(0, 20)
plt.xticks(ticks, labels)
ax.set_title('Smoothness With Sampling Num')
plt.savefig('./picture/draw2.png')
plt.show()